/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.windows; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import javax.swing.MenuSelectionManager; import javax.swing.SwingUtilities; import javax.swing.MenuElement; import org.openide.TopManager; import org.openide.windows.TopComponent; import org.openide.windows.Workspace; import org.openide.nodes.Node; import org.openide.util.WeakSet; /** Implementstion of registry of top components. This implementation * receives information about top component changes from the window * manager implementation, to which is listening to. * * @author Dafe Simonek */ final class RegistryImpl extends Object implements TopComponent.Registry, TopComponentListener, StateManager.StateListener { // fields /** Activated top component */ private TopComponent activatedTopComponent; /** Set of opened TopComponents */ private HashSet openSet; /** Currently selected nodes. */ private Node[] current; /** Last non-null value of current nodes */ private Node[] activated; /** PropertyChange support */ private PropertyChangeSupport support; /** state support for window manager */ private StateManager stateManager; /** Creates new RegistryImpl */ public RegistryImpl () { support = new PropertyChangeSupport(this); openSet = new HashSet(30); activated = new Node[0]; } /** Get all opened componets in the system. * * @return immutable set of {@link TopComponent}s */ public synchronized Set getOpened() { return java.util.Collections.unmodifiableSet(openSet); } /** Get the currently selected element. * @return the selected top component, or <CODE>null</CODE> if there is none */ public TopComponent getActivated () { return activatedTopComponent; } /** Getter for the currently selected nodes. * @return array of nodes or null if no component activated or it returns * null from getActivatedNodes (). */ public Node[] getCurrentNodes () { return current; } /** Getter for the lastly activated nodes. Comparing * to previous method it always remembers the selected nodes * of the last component that had ones. * * @return array of nodes (not null) */ public Node[] getActivatedNodes () { return activated; } /** Add a property change listener. * @param l the listener to add */ public void addPropertyChangeListener (PropertyChangeListener l) { support.addPropertyChangeListener(l); } /** Remove a property change listener. * @param l the listener to remove */ public void removePropertyChangeListener (PropertyChangeListener l) { support.removePropertyChangeListener(l); } /** Called when a TopComponent is activated. * * @param ev TopComponentChangedEvent */ public void topComponentActivated(TopComponentChangedEvent ev) { TopComponent old = activatedTopComponent; activatedTopComponent = ev.topComponent; java.awt.Window w = ev.topComponent == null ? null : SwingUtilities.windowForComponent(ev.topComponent); cancelMenu (w); if (old == activatedTopComponent) { return; } support.firePropertyChange(PROP_ACTIVATED, old, activatedTopComponent); } /** Called when a TopComponent is opened. * * @param ev TopComponentChangedEvent */ public synchronized void topComponentOpened(TopComponentChangedEvent ev) { if (openSet.contains(ev.topComponent)) { return; } Set old = (Set) openSet.clone(); openSet.add(ev.topComponent); support.firePropertyChange(PROP_OPENED, old, openSet); } /** Called when a TopComponent is closed. * * @param ev TopComponentChangedEvent */ public synchronized void topComponentClosed(TopComponentChangedEvent ev) { if (! openSet.contains(ev.topComponent)) { return; } // we should remove it from the set only if it is closed // on all workspaces WindowManagerImpl wm = (WindowManagerImpl)TopManager.getDefault().getWindowManager(); Workspace[] workspaces = wm.getWorkspaces(); for (int i = 0; i < workspaces.length; i++) { if (wm.findManager(ev.topComponent).isOpened(workspaces[i])) return; } // conditions satisfied, now remove... Set old = (Set) openSet.clone(); openSet.remove(ev.topComponent); support.firePropertyChange(PROP_OPENED, old, openSet); } /** Called when selected nodes change.. * * @param ev TopComponentChangedEvent */ public void selectedNodesChanged(SelectedNodesChangedEvent ev) { Node[] old = current; Node[] c = ev.getSelectedNodes(); if (Arrays.equals(old, c)) { return; } if (stateManager == null) { // initialize and start to listen to state changes stateManager = ((WindowManagerImpl)TopManager.getDefault(). getWindowManager()).stateManager(); stateManager.addStateListener(this); } current = c == null ? null : (Node[])c.clone (); // fire immediatelly only if window manager in proper state tryFireChanges(stateManager.getState(), old, current); } /** called when state of window manager changes */ public void stateChanged (int state) { tryFireChanges(state, null, current); } /** If window manager in proper state, fire selected and * activated node changes */ private void tryFireChanges (int state, Node[] oldNodes, Node[] newNodes) { if (state == (StateManager.READY | StateManager.VISIBLE)) { support.firePropertyChange(PROP_CURRENT_NODES, oldNodes, newNodes); if (newNodes != null) { oldNodes = activated; activated = newNodes; support.firePropertyChange(PROP_ACTIVATED_NODES, oldNodes, activated); } } else { // defer firing, do nothing now //System.out.println("Deferred firing..."); // NOI18N } } /** * Cancels the menu if it is not assigned to specified window. * @param window window that the menu should be checked against (if this * window contains the menu, then the menu will not be closed) */ /** Closes popup menu. */ private static void cancelMenu (java.awt.Window window) { MenuSelectionManager msm = MenuSelectionManager.defaultManager(); MenuElement[] path = msm.getSelectedPath (); for (int i = 0; i < path.length; i++) { // if (newPath[i] != path[i]) return; java.awt.Window w = SwingUtilities.windowForComponent( path[i].getComponent() ); if (w == window || w.getOwner() == window) { // ok, this menu can stay return; } } msm.clearSelectedPath (); } } /* * Log * 10 Gandalf 1.9 1/13/00 David Simonek i18n * 9 Gandalf 1.8 12/17/99 David Simonek #1913, #2970 * 8 Gandalf 1.7 12/3/99 Jaroslav Tulach Activated/Current works * better. * 7 Gandalf 1.6 11/24/99 Jaroslav Tulach Does not keep values of * old selected nodes. Which protected them from garbage collection. * 6 Gandalf 1.5 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 5 Gandalf 1.4 9/8/99 David Simonek deferred opening and * firing of selected nodes, state management * 4 Gandalf 1.3 7/28/99 David Simonek workspace serialization * bugfixes * 3 Gandalf 1.2 7/21/99 David Simonek window system updates... * 2 Gandalf 1.1 7/20/99 David Simonek various window system * updates * 1 Gandalf 1.0 7/11/99 David Simonek * $ */